﻿using System;
using System.IO;
using System.Xml.Serialization;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TransactionServer.General_Classes;
using TransactionServer.GP.Classes;

namespace TransactionServer.FileActivities
{
    public class FileConnector : ISystemConnector
    {
        public string connection;

        private List<string> files;
        public string GetNextFile()
        {
            string result = String.Empty;
            if (files != null && files.Count > 0)
            {
                result = files[0];
                files.RemoveAt(0);
            }
            else
            {
                files = Directory.GetFiles(path).ToList<string>();
                if (files != null && files.Count > 0)
                {
                    result = files[0];
                    files.RemoveAt(0);
                }
                else
                {
                    result = null;
                }
            }

            return result;
        }

        private string _path;
        public string path
        {
            get
            {
                if (String.IsNullOrEmpty(_path))
                {
                    _path = settings["path"];
                }
                return _path;
            }
        }

        private string _assemblyName;
        public string assemblyName
        {
            get
            {
                if (String.IsNullOrEmpty(_assemblyName))
                {
                    _assemblyName = settings["assemblyname"];
                }
                return _assemblyName;
            }
        }

        private string _connectionName;
        public string connectionName
        {
            get
            {
                if (String.IsNullOrEmpty(_connectionName))
                {
                    _connectionName = settings["connection"];
                }
                return _connectionName;
            }
        }


        public FileConnector(Dictionary<string, string> settings) : base(settings)
        {
        }


        // TODO Add sorting by created date
        public override Event getNextEvent()
        {
            string xml = String.Empty;
            string curFile = String.Empty;

            while ((curFile = GetNextFile()) != null)
            {
                try
                {
                    xml = File.ReadAllText(curFile);
                }
                catch
                {
                    continue;
                }
                break;
            }

            if (!String.IsNullOrEmpty(xml))
            {
                StringReader sr = new StringReader(xml);
                var serializer = new XmlSerializer(typeof(Event));

                File.Delete(curFile);
                return (Event)serializer.Deserialize(sr);
            }
            else
            {
                return null;
            }

        }

        public override List<string> getEntities()
        {
            var assembly = Assembly.LoadFrom(assemblyName);
            var entities = (from entity in assembly.GetTypes() where entity.BaseType == typeof(Entity) select entity.Name).ToList();

            return entities;
        }

        public override List<string> getAttributes(string entity)
        {
            var result = new List<string>();

            var properties = Type.GetType(String.Format("{0}.{1}, {0}", Path.GetFileNameWithoutExtension(assemblyName), entity)).GetFields();

            var entityProperties = typeof(Entity).GetFields();

            foreach (var property in properties)
            {
                var matchingProperties = (from prop in entityProperties where prop.Name == property.Name select 1).ToList();
                if (matchingProperties.Count <= 0)
                {
                    result.Add(property.Name);                    
                }
            }

            return result;
        }

        public Entity convertToDynamic(Entity entity)
        {          
            var result = new Entity()
            {
                System = connectionName,
                Id = entity.Id,
                Name = entity.GetType().Name
            };

            var type = entity.GetType();
            var entityProperties = typeof(Entity).GetFields();

            foreach (var property in type.GetFields())
            {
                var matchingProperties = (from prop in entityProperties where prop.Name == property.Name select 1).ToList();
                if (matchingProperties.Count <= 0)
                {
                    result[property.Name] = property.GetValue(entity);                    
                }
            }

            return result;
        }

        public void AddEvent(MessageName message, Entity entity)
        {
            var transactionEntity = convertToDynamic(entity);

            var Event = new Event()
                {
                    MessageName = message.ToString(),
                    OccuredOn = DateTime.UtcNow,
                    Entity = transactionEntity
                };
            
            var serializer = new XmlSerializer(typeof(Event));

            TextWriter tw = new StreamWriter(String.Format(@"{0}\{1}.xml", path, Guid.NewGuid().ToString()), true, Encoding.GetEncoding(1251));
            serializer.Serialize(tw, Event);            
            tw.Close();

        }

        /// <summary>
        /// Checks the health.
        /// </summary>
        /// <returns></returns>
        public override HealthInfo CheckHealth()
        {
            var healthInfo = new HealthInfo()
            {
                ServiceName = GetType().FullName
            };

            try
            {
                healthInfo.Status = Directory.Exists(_path); ;
            }
            catch (Exception exc)
            {
                healthInfo.Status = true;
                healthInfo.ErrorInfo = string.Format("{0}\n{1}", exc.Message, exc.StackTrace);
            }

            return healthInfo;
        }

        public override void close()
        {
            
        }
    }
}
